dskjal
広告
広告

ComfyUI で使える高速化・VRAM 技術

カテゴリ:deeplearning

ComfyUI は PyTorch attention = FlashAttention がデフォルトで使われる。昔は xformers(中身は FlashAttention)も使われていたが、最近では PyTorch attention を使うことが多い。

ComfyUI のオプションは comfy/cli_args.py を見るのが早い。

目次

ComfyUI のメモリ管理

モデルを VRAM に移動しても RAM 上のモデルは解放されないことに注意。モデルをオフロードすると RAM の使用量が増減すると勘違いしている人が非常に多い。タスクマネージャを見れば、一度モデルがロードされれば RAM の使用量はほとんど変化していないことが検証できる。つまりモデルを RAM にロードして、推論に必要な部分だけを VRAM に転送しているだけだ。

ComfyUI のデフォルト挙動

ComfyUI のデフォルト挙動はワークフローで使うモデルをすべて RAM にロードし、実行中はアンロードしない。Wan 2.2 を fp16 で実行する場合、最低 68.4 GB の RAM が必要になる。Q4_K_M を使う場合は 31 GB の RAM が必要。

モデルサイズ(GB)
umt5_xxl_fp89.0
wan2.2_vae1.4
high-fp1629.0
low-fp1629.0

cache-none

--cache-none は RAM も不足している環境で RAM のキャッシュを無効化する。スワップが発生し SSD に書き込みが発生するよりは、毎回 SSD から読み込んだ方がましな状況では使える。

ただし「RAM の量 < モデルサイズ」の環境では、スワップを回避できない。

モデルと VRAM

画像生成モデルの場合、モデルサイズ ≒ VRAM 使用量だが、動画生成モデルでは違う。

動画生成モデルは生成途中の動画データも数 GB の VRAM を使用するので、モデルサイズだけで VRAM が足りるかどうかを判定できない。

RTX 5090 は VRAM 32 GB で Wan 2.2 fp16 は 29 GB なので、モデルがすべて VRAM に乗ると考えがちだが、生成動画分の VRAM と OS 管理分とが必要なので足りない。

PCI Express の帯域がボトルネックになることはまずない

4.0 は2GB/レーン なので、x16 なら 32 GB/s。5.0 は4GB/レーンなので、x16 なら 64GB/s。

モデルの半分以上が VRAM に乗らない場合、推論1回あたりのデータ転送量はモデルサイズと同じになる。このような巨大なモデルで 1 it/s を超えることはないので、PCI Express の帯域がボトルネックになることはまずない。

20 GB のモデルで VRAM に 15 GB 乗っている場合、推論1回あたりのデータ転送量は 10 GB(不足分5GB + 次回推論時に VRAM から削除した分の再ロード5GB)になる。このケースで PCI Express 4.0 x16 の場合は、3 it/s までは PCI Express の帯域はボトルネックにならない。

これは演算ボトルネックの画像・動画生成の場合であって、メモリ速度ボトルネックの LLM では PCI Express の帯域がボトルネックになりうる。DDR5 デュアルチャンネルの帯域 > PCI Express 5.0 x16 の帯域なので。

SSD へのスワップの監視

Windows のタスクマネージャのメモリを見てもスワップはわからない。

生成中に SSD の「書き込み速度」が 100MB/秒 を超えるようならスワップが発生している可能性が高い。

ComfyUI のメモリ使用量

タスクマネージャのプロセスタブの python を見るのが早い。

タスクマネージャのメモリタブ
項目意味
使用中(圧縮)使用中の物理メモリ量
利用可能空き物理メモリ量
コミット済みメモリアドレスが予約済みのメモリ量。
予約されていても読み書きが発生していない状態では、物理メモリにもストレージにも領域確保は発生しない
キャッシュ済み最近使用したデータを再利用するための一時的なメモリ領域
ページプールWindows カーネルが使用するメモリで、ストレージ等に退避可能なメモリ領域。
気にする必要はない
非ページプールWindows カーネルが使用するメモリで、ストレージ等に退避不可能なメモリ領域。
気にする必要はない

「コミット済み - 使用中 = スワップ量」のような間違いを信じている人が非常に多い。メモリはアドレスを予約した後、実際に読み書きされるまで、物理メモリやストレージの領域確保は発生しない。なのでコミット済みを見てもどれだけのスワップが発生しているかはわからない。

VirtualAlloc に MEM_RESET を指定すれば、メモリアドレスを維持したまま物理メモリを解放できる。なので、「コミット済み」を変化させずに「使用中(圧縮)」の量を減らすことも可能。

VRAM

GGUF

GGUF はモデル量子化技術。RAM から VRAM へ必要な量だけ転送して実行する。

Block Swap(非推奨)

VRAM のモデルのブロックを交換しつつモデルを実行できる。ComfyUI 自体にこの機能が実装されているので、ComfyUI 0.3.70 以降は Block Swap ノードは非推奨となっている。

ComfyUI-MultiGPU DisTorch 2.0

複数 GPU の VRAM と RAM とに好きなようにブロックを割り付けできる

raylight

複数 GPU に分割してモデルを配置でき、それぞれの GPU で独立して画像を同時に生成できる。SD 1.5 と SDXL には非対応。

1枚だけ生成する速度は高速化しないが、複数枚生成する場合のスループットは向上する。たとえば、RTX5090(45万円)で2枚生成する速度と RTX5070Ti(13万円*2 = 26万円)2台で同時に1枚ずつ生成する速度とが大体同じ。

プロンプトや設定の検証を低コストで効率化できる。

pinned-memory

RAM に確保したモデルがページングされなくなる。ページングとは RAM も VRAM も不足した場合、OS が SSD や HDD を使って処理を継続する機能。pinned-memory はこれを無効化する。

つまり pinned-memory が有効な状態で RAM も VRAM も不足すると OOM が発生する。

pinned-memory を無効にするには --disable-pinned-memory オプションをつけて ComfyUI を起動する。

python main.py --disable-pinned-memory

reserve-vram

OS が利用する VRAM 量を指定する。Kijai は --reserve-vram 2 を指定することを推奨している。

最新の ComfyUI は自動で VRAM と RAM とにモデルを割り振る。しかし、OS が VRAM を使用して VRAM が不足すると共有 VRAM が使用され、生成速度が劇的に低下する。reserve-vram はこれを回避できる。

当然 ComfyUI が使用できる VRAM 量が減少するため生成速度は低下する可能性が高い。

python main.py --reserve-vram 2

highvram

ComfyUI の実行フロー

highvram を指定するとモデルを VRAM から削除しなくなる。

python main.py --highvram

モデルウェイト最適化

量子化

量子化はモデルの表現ビット数を減らしてモデルサイズを減らす。VRAM 速度がボトルネックの場合は推論速度も上がる。メモリ速度がボトルネックになっている LLM では量子化で推論速度も上がるが、演算ボトルネックの画像・動画生成 AI では推論速度は上がらない。

手法説明
GGUF拡張子が GGUF のモデル。VRAM にモデルが乗らなくても RAM から VRAM にブロックを転送して実行可能
fp8RTX 4000 番台以降ではハードウェアで高速に実行できる
DFloat1111bit で圧縮して演算時に bf16 に展開する。高速化はしないがロスレス圧縮なので、劣化なしで bf16 を 30% 圧縮できる
SVDQuantモデルを外れ値とそうでない部分とに分けて量子化する手法。nuncyaku という名前で呼ばれている
TensorRT量子化+生成解像度指定等の最適化で効率的に実行できるようにモデルを変換して高速化する
NVFP4fp4 量子化(e2m1)+16 ブロックごとに fp8 スケール値+2テンソルごとに fp32 スケール値
SageAttentionFlashAttention-2 を INT8 や INT4 で量子化する
量子化比較

fp8 はRTX 4000 番台以降での評価、NVFP4 は 5000 番台以降の評価。scaled_fp8 は高品質かつ高速なのでベストな選択。

手法品質推論速度
Q8_0fp16 に匹敵遅い
scaled_fp8Q8_0 に匹敵速い
fp8Q5_K_M や Q6_K_M 相当速い
NVFP4fp8 相当とても速い

蒸留

教師モデルを模倣し、低ステップで生成できるように訓練されたモデル。

モデルファイル名に 4step や 8step が入っていると蒸留モデルの可能性が高い。最近は LoRA 形式で配布されることが多い。

GGUF のアルゴリズム

GGUF は fp8 や bf16 でデータを持つこともできるが、普通は Q8_0 や Q4_K_M のような整数でデータを持っている。LLM の場合は llama_cpp ライブラリを使えば整数のまま計算できる。画像生成 AI の場合は、計算する前に整数を fp16 に変換してから計算するため、fp16 や bf16 に比べて若干遅くなる。Unet Loader GGUF/Advanced ノードを使えば、計算精度に bf16 や fp32 のようなデータタイプも選択できる。

NVFP4 の解説

NVFP4 は FP4 で精度を維持する工夫であって、MXFP4 と同様にハードウェアは従来の FP4 演算器を使う。

MXFP4

MXFP4 は 32 値ブロックごとに1つスケールパラメータをもつ。Blackwell アーキテクチャの GPU は、この「スケール適用+演算」を1命令でできるようにした MXFP4 / MXFP8 を持っている(専用の演算器を持っているのではなく最適化によって実現している。演算自体は FP4 を使う)。

NVFP4

NVFP4 は 16 値ブロックごとに1つ fp8 スケールパラメータを持ち、テンソルごとに fp32 のスケールパラメータを持つ。これも演算自体は FP4 を使う。

外部リンク

Introducing NVFP4 for Efficient and Accurate Low-Precision Inference

Pretraining Large Language Models with NVFP4

コード最適化

FlashAttention

pytorch 2.2 で FlashAttention-2 に対応し、約2倍高速化した

pytorch 2.5 で cuDNN バックエンドの統合により scaled dot product attention(SDPA)が FlashAttention-2 比で 75% 高速化した。H100 以降の業務用 GPU では cuDNN バックエンドの SDPA がデフォルトで使われる。

FlashAttention-3 は H100 以降の業務用 GPU で使用でき、FlashAttention-2 より 50%~100% 高速。

torch.compile

モデルをネイティブコードに変換して高速化する。SageAttention と同時に使われることが多い。

ComfyUI 公式の TorchCompileModel ノードでできる。初回実行時、モデルのコンパイルに数分かかる。モデルによっては機能しない。

triton

モデルのコードをカスタム GPU カーネルに変換するライブラリ。SageAttention と同時に使われることが多い。

Windows 用バイナリも増えてきて簡単にインストールできるようになった。インストールは RTX3050+ComfyUI で SageAttention の導入を参照。

SageAttention

アテンションの計算に SageAttention を使うことで高速化する。SDXL は U-Net を使用しており、アテンションはプロンプトの取り込み部分にしか使われていないので、SDXL は SageAttention を使ってもほとんど高速化しない。

SDXL 以降の画像生成・動画生成 AI は拡散トランスフォーマーなので SageAttention で高速化できる。

kijai/ComfyUI-KJNodes の Patch Sage Attention KJ ノードはノード上で SageAttention の適用を切り替えられる。

TeaCache

「モデルに入力するノイズ画像 - デノイズ後の画像」の差分ベクトルはステップ中盤以降はほとんど変化しないことが多い。なのでこの差分ベクトルをキャッシュして使いまわしてデノイズすることで、推論を丸ごとスキップして高速化する。

--fast オプション

試験的な機能を有効にする。たとえば ComfyUI バージョン 0.8 では以下の機能が有効になる。

class PerformanceFeature(enum.Enum):
    Fp16Accumulation = "fp16_accumulation"
    Fp8MatrixMultiplication = "fp8_matrix_mult"
    CublasOps = "cublas_ops"
    AutoTune = "autotune"
fp16_accumulation

行列演算の中間結果の精度を fp16 にすることで高速化+メモリ使用量を削減する。やっていることは torch.backends.cuda.matmul.allow_fp16_accumulation = True の設定だけ。

kijai/ComfyUI-KJNodes の Model Patch Torch Settings ノードは fp16_accumulation をノード上で切り替えできる。

fp16_accumulation は fp8 モデルでも高速化することがある。z-image-turbo_fp8_scaled_e4m3fn_KJ.safetensors を見てもらえれば分かるが、fp8 なのは大部分を占めるウェイトだけで、スケールやバイアスは fp32 が使われている。fp32 と fp8 との演算は fp32 が使われるため、これが fp16 化されるので高速化する。

fp8_matrix_mult

Linear に fp8_ops を使う。ハードウェアで fp8 演算が可能な RTX4000 番台以降では高速化する可能性が高い。

cublas_ops

Linear に cuBLAS を使う。cuBLAS は CUDA で書かれた線形代数ライブラリ

日本語の解説は cuBLASってなんだ?―― 行列演算を爆速にする縁の下の力持ちを参照。

fp8_matrix_mult vs cublas_ops

fp8_matrix_mult と cublas_ops とはどちらかしか利用できない。デフォルトでは fp8_matrix_mult が優先される

AutoTune

torch.backends.cudnn.benchmark = True を実行する。pytorch のバージョンが 2.5 以上なら torch.backends.cuda.allow_fp16_bf16_reduction_math_sdp(True) も実行する

cudnn のベンチマークモードは実行前にハードウェアやモデルを調査し、最適なアルゴリズムを自動的に選択する。一度選択されると、バックエンド起動中は変更されない。モデルや入力解像度が固定されている場合は高速化するが、そうでない場合は逆に遅くなることもある。

AutoTune が有効な場合、cuda_malloc は無効になる


広告
広告

カテゴリ